package com.adjy.pathbuilders.physics;

import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.contacts.Contact;

/**
 * PhysicalObject hold properties of a PhysicalObject such as<br>
 * Position, Width, Height, etc
 */
public abstract class PhysicalObject {

	private BoundingBox boundingVolume;
	private boolean collidable;
	private boolean sufferGravity;
	private float vX = 0, vY = 0;
	private boolean dynamic;
	private Body body;

	/**
	 * Creates a PhysicalObject with the given properties
	 * 
	 * @param x
	 *            X Position
	 * @param y
	 *            Y Position
	 * @param width
	 *            Width of this Object
	 * @param height
	 *            Height of this Object
	 */
	public PhysicalObject(float x, float y, float width, float height) {
		this(x, y, width, height, true, true, false);
	}

	/**
	 * Creates a PhysicalObject with the given properties
	 * 
	 * @param x
	 *            X Position
	 * @param y
	 *            Y Position
	 * @param width
	 *            Width of this Object
	 * @param height
	 *            Height of this Object
	 * @param sufferGravity
	 *            Boolean to enable gravity for this Object
	 */
	public PhysicalObject(float x, float y, float width, float height,
			boolean sufferGravity) {
		this(x, y, width, height, sufferGravity, true, false);
	}

	/**
	 * Creates a PhysicalObject with the given properties
	 * 
	 * @param x
	 *            X Position
	 * @param y
	 *            Y Position
	 * @param d
	 *            Width of this Object
	 * @param height
	 *            Height of this Object
	 * @param sufferGravity
	 *            Boolean to enable gravity for this Object
	 * @param collidable
	 *            If this Object should be a solid collidable in the
	 *            PhysicsWorld
	 * @param dynamic
	 *            If this Object is capable of Moving or Changing its position
	 */
	public PhysicalObject(float x, float y, float d, float height,
			boolean sufferGravity, boolean collidable, boolean dynamic) {
		this.boundingVolume = new BoundingBox(x, y, d, height);
		this.sufferGravity = sufferGravity;
		this.collidable = collidable;
		this.dynamic = dynamic;
	}

	/**
	 * Adds Velocity to the Y Axis
	 * 
	 * @param vel
	 *            Velocity to be added
	 * @return Y Velocity
	 */
	public float addYVelocity(float vel) {
		vY += vel;
		return vY;
	}

	/**
	 * Adds Velocity to the X Axis
	 * 
	 * @param vel
	 *            Velocity to be added
	 * @return X Velocity
	 */
	public float addXVelocity(float vel) {
		vX += vel;
		return vX;
	}

	/**
	 * Sets X Velocity
	 * 
	 * @param xVel
	 *            New X Velocity
	 */
	public void setXVelocity(float xVel) {
		this.vX = xVel;
	}

	/**
	 * Sets Y Velocity
	 * 
	 * @param yVel
	 *            New Y Velocity
	 */
	public void setYVelocity(float yVel) {
		this.vY = yVel;
	}

	/**
	 * Resets velocities
	 */
	public void resetVelocities() {
		vX = 0;
		vY = 0;
	}

	/**
	 * Checks if this entity is affected by gravity
	 * 
	 * @return True - It is affected by gravity<br>
	 *         False - It is not affected by gravity
	 */
	public boolean isAffectedByGravity() {
		return sufferGravity;
	}

	/**
	 * Sets if this PhysicalObject should be affected by gravity from now on
	 * 
	 * @param isAffected
	 *            True - Is Affected by Gravity<br>
	 *            False - Isn't Affected by Gravity
	 */
	public void setAffectedByGravity(boolean isAffected) {
		this.sufferGravity = isAffected;
	}

	/**
	 * Checks if this object is Collidable
	 * 
	 * @return True - Object is Collidable<br>
	 *         False - Object isnt Collidable
	 */
	public boolean isCollidable() {
		return collidable;
	}

	public float getXVelocity() {
		return vX;
	}

	public float getYVelocity() {
		return vY;
	}

	public boolean isDynamic() {
		return dynamic;
	}

	/**
	 * Return the BoundingVolume for this PhysicalObject
	 * 
	 * @return BoundingVolume
	 */
	public Vec2 getCenter() {
		return new Vec2(boundingVolume.getX(), boundingVolume.getY());
	}

	/**
	 * PhysicalObject's Handler for when a collision happens with another
	 * PhysicalObject
	 * 
	 * @param pObject
	 *            PhysicalObject it has collided
	 * @param contact TODO
	 */
	public abstract void hasStartedCollidingWith(PhysicalObject pObject, Contact contact);
	
	public void hasStoppedCollidingWith(PhysicalObject pObject, Contact contact) {
		// Does nothing
	}
	
	public Body getBody() {
		return this.body;
	}
	
	public void setBody(Body b) {
		this.body = b;
	}
	
	public float getWidth() {
		return boundingVolume.getWidth();
	}
	
	public float getHeight() {
		return boundingVolume.getHeight();
	}
	
	public float getX() {
		return boundingVolume.getX();
	}
	
	public float getY() {
		return boundingVolume.getY();
	}
	
	public void setX(int x) {
		boundingVolume.setX(x);
	}
	
	public void setY(int y) {
		boundingVolume.setY(y);
	}

}
